﻿using System;
using System.Collections.Generic;
using System.Linq;
using Missbot.Common;
using Missbot.Core.Base;
using Missbot.Core.Cache;
using Dolany.UtilityTool;
using JetBrains.Annotations;
using Missbot.AIModule.Base;
using Missbot.AIModule.OnlineStore;
using Missbot.AIModule.Pet.Cooking;
using Missbot.AIModule.Vip;

namespace Missbot.AIModule.Pet.Expedition
{
    [UsedImplicitly]
    public class ExpeditionMod : IAIModule
    {
        public override string Name => "宠物远征";
        public override string ParentTag => "宠物功能";

        #region Svcs

        public ExpeditionSceneSvc ExpeditionSceneSvc { get; set; }
        public PetLevelSvc PetLevelSvc { get; set; }
        public WaiterSvc WaiterSvc { get; set; }
        public HonorSvc HonorSvc { get; set; }

        #endregion

        [ModuleEnter(Command = "宠物远征", Description = "开始宠物远征，或者领取远征奖励")]
        public bool Expedite(InboxSession session)
        {
            var expeditionRec = ExpeditionRecordDA.GetLastest(session.User.ID);
            if (expeditionRec == null)
            {
                return StartExpedite(session);
            }

            var pet = PetRecordDA.Get(session.User.ID);
            if (expeditionRec.IsExpediting())
            {
                session.SendBack($"{pet.Name}还在远征中，请于 {expeditionRec.EndTime:yyyy-MM-dd HH:mm:ss}后再试！");
                return false;
            }

            if (expeditionRec.IsDrawn)
            {
                return StartExpedite(session);
            }

            DrawAwards(expeditionRec, session);
            return true;
        }

        private bool StartExpedite(InboxSession session)
        {
            var extEndur = VipArmerDA.Get(session.User.ID)?.CheckArmer("耐力护符") ?? false ? 10 : 0;

            var pet = PetRecordDA.Get(session.User.ID);
            var petLevel = PetLevelSvc[pet.Level];
            var enduranceConsume = PetEnduranceDA.Get(session.User.ID);
            var curEndurance = petLevel.Endurance - enduranceConsume.ConsumeTotal + extEndur;

            var todayExpeditions = ExpeditionSceneSvc.TodayExpedition().Where(p => p.Endurance <= curEndurance).ToList();
            if (todayExpeditions.IsNullOrEmpty())
            {
                session.SendBack($"{pet.Name}已经累的完全动不了了！");
                return false;
            }

            var msg = $"请选择远征副本：\n{todayExpeditions.Select((exp, idx) => $"{idx + 1}:{exp.Format(curEndurance)}").JoinToString("\n")}";
            var selection = WaiterSvc.WaitForNum(session, msg, i => i > 0 && i <= todayExpeditions.Count);
            if (selection < 0)
            {
                session.SendBack("操作取消");
                return false;
            }

            var aimExpedition = todayExpeditions[selection - 1];
            var expRec = new ExpeditionRecord
            {
                EndTime = DateTime.Now.AddMinutes(aimExpedition.TimeConsume),
                UserID = session.User.ID,
                Scene = aimExpedition.Name
            };
            expRec.Insert();

            enduranceConsume.ConsumeTotal += aimExpedition.Endurance;
            enduranceConsume.Update();

            session.SendBack($"远征开始！目标：【{aimExpedition.Name}】！(请于{expRec.EndTime:yyyy-MM-dd HH:mm:ss}后使用 宠物远征 命令回收远征奖励！)");
            return true;
        }

        private void DrawAwards(ExpeditionRecord expeditionRec, InboxSession session)
        {
            var expeditionModel = ExpeditionSceneSvc[expeditionRec.Scene];
            var award = expeditionModel.Award(session.User.ID);
            session.SendBack(award.ToString());

            expeditionRec.IsDrawn = true;
            expeditionRec.Update();

            var history = ExpeditionHistoryDA.Get(session.User.ID);
            history.AddScene(expeditionModel.Name);
            history.EnduranceConsume += expeditionModel.Endurance;
            history.FlavoringTotal += award.Flavorings.Count;
            history.GoldsTotal += award.Gold;
            history.ItemBonusCount += award.Items.Count;
            history.ItemBonusPriceTotal += award.Items.Sum(item => HonorSvc.FindItem(item).Price);

            history.Update();
        }

        [ModuleEnter(Command = "查看远征地点", Description = "查看某个远征地点的信息", SyntaxHint = "[远征地点名]")]
        public bool ViewExpedition(InboxSession session, string name)
        {
            var scene = ExpeditionSceneSvc[name];
            if (scene == null)
            {
                session.SendBack("未查找到相关地点！");
                return false;
            }

            session.SendBack(scene.Format());
            return true;
        }

        [ModuleEnter(Command = "我的远征记录", Description = "查看我的远征记录")]
        public bool MyExpeditionHistory(InboxSession session)
        {
            var history = ExpeditionHistoryDA.Get(session.User.ID);
            if (history.SceneDic.IsNullOrEmpty())
            {
                session.SendBack("尚未记录到远征信息！");
                return false;
            }

            var hotScenes = history.SceneDic.OrderByDescending(p => p.Value).Take(3).ToList();
            var buffer = new OutputBuffer(session);
            buffer.AddPair(new Dictionary<string, string>
            {
                ["你最热衷的远征地点"] = hotScenes.Select(s => $"{s.Key}*{s.Value}次").JoinToString(","),
                ["共获得金币"] = history.GoldsTotal.CurencyFormat(),
                ["共获得调味料"] = $"{history.FlavoringTotal}个",
                ["共获得物品"] = $"{history.ItemBonusCount}个",
                ["物品总价值"] = history.ItemBonusPriceTotal.CurencyFormat()
            });

            buffer.Send();
            return true;
        }

        [ModuleEnter(Command = "分解 分解物品", Description = "将某个物品分解为调味料", DailyLimit = 5, SyntaxHint = "[物品名]")]
        public bool ResolveItem(InboxSession session, string name)
        {
            var item = HonorSvc.FindItem(name);
            if (item == null)
            {
                session.SendBack("未查找到相关物品！");
                return false;
            }

            var itemColle = ItemCollectionDA.Get(session.User.ID);
            if (!itemColle.CheckItem(name))
            {
                session.SendBack("你尚未持有该物品！");
                return false;
            }

            itemColle.ItemConsume(name);
            itemColle.Update();

            var count = Math.Max(item.Price / 20, 1);
            var flavorings = ExpeditionSceneSvc.RandFlavorings(count);

            var cookingRec = CookingRecordDA.Get(session.User.ID);
            cookingRec.FlavoringIncome(flavorings);
            cookingRec.Update();

            var msg = flavorings.Select(p => $"{p.Key}×{p.Value}").JoinToString(",");
            session.SendBack($"分解成功！你获得了：\n{msg}");
            return true;
        }
    }
}